<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<link rel="up" title="FatFs" href="../00index.html">
<link rel="stylesheet" href="../css_e.css" type="text/css" media="screen" title="ELM Default">
<title>TJpgDec Module Application Note</title>
</head>


<body>
<h1>TJpgDec Module Application Note</h1>
<ol class="toc">
<li><a href="#use">How to Use</a></li>
<li><a href="#limits">Limits</a></li>
<li><a href="#memory">Memory Usage</a></li>
<li><a href="#license">About TJpgDec License</a></li>
</ol>
<hr>

<div class="para" id="use">
<h3>How to Use</h3>
<p>First of all, you should build and run the sample program shown below. This is a typical usage of TJpgDec module and it helps to narrow down the problem on debugging.</p>
<p>The decompression session is divided in two stages. The first stage is to analyze the JPEG image and the second stage is to decompress it.</p>
<ol>
<li>Initialize input stream. (e.g. open a file)</li>
<li>Allocate JPEG decompression object and work area.</li>
<li>Call <em>jd_prepare()</em> to analyze and prepare to decompress the JPEG image.</li>
<li>Initialize output device with the image info in the decompression object.</li>
<li>Call <em>jd_decomp()</em> to decompress the JPEG image.</li>
</ol>

<h4>System Organization</h4>
<p><img src="p1.png" width="420" height="280" alt=""></p>

<h4>Example</h4>
<pre>
<span class="c">/*------------------------------------------------*/</span>
<span class="c">/* TJpgDec Quick Evaluation Program for PCs       */</span>
<span class="c">/*------------------------------------------------*/</span>

<span class="k">#include</span> &lt;stdio.h&gt;
<span class="k">#include</span> &lt;string.h&gt;
<span class="k">#include</span> "tjpgd.h"


<span class="c">/* User defined device identifier */</span>
<span class="k">typedef struct</span> {
    FILE *fp;      <span class="c">/* File pointer for input function */</span>
    BYTE *fbuf;    <span class="c">/* Pointer to the frame buffer for output function */</span>
    UINT wfbuf;    <span class="c">/* Width of the frame buffer [pix] */</span>
} IODEV;


<span class="c">/*------------------------------*/</span>
<span class="c">/* User defined input funciton  */</span>
<span class="c">/*------------------------------*/</span>

UINT in_func (JDEC* jd, BYTE* buff, UINT nbyte)
{
    IODEV *dev = (IODEV*)jd-&gt;device;   <span class="c">/* Device identifier for the session (5th argument of jd_prepare function) */</span>


    if (buff) {
        <span class="c">/* Read bytes from input stream */</span>
        return (UINT)fread(buff, 1, nbyte, dev-&gt;fp);
    } else {
        <span class="c">/* Remove bytes from input stream */</span>
        return fseek(dev-&gt;fp, nbyte, SEEK_CUR) ? 0 : nbyte;
    }
}


<span class="c">/*------------------------------*/</span>
<span class="c">/* User defined output funciton */</span>
<span class="c">/*------------------------------*/</span>

UINT out_func (JDEC* jd, void* bitmap, JRECT* rect)
{
    IODEV *dev = (IODEV*)jd-&gt;device;
    BYTE *src, *dst;
    UINT y, bws, bwd;


    <span class="c">/* Put progress indicator */</span>
    if (rect-&gt;left == 0) {
        printf("\r%lu%%", (rect-&gt;top &lt;&lt; jd-&gt;scale) * 100UL / jd-&gt;height);
    }

    <span class="c">/* Copy the decompressed RGB rectanglar to the frame buffer (assuming RGB888 cfg) */</span>
    src = (BYTE*)bitmap;
    dst = dev-&gt;fbuf + 3 * (rect-&gt;top * dev-&gt;wfbuf + rect-&gt;left);  <span class="c">/* Left-top of destination rectangular */</span>
    bws = 3 * (rect-&gt;right - rect-&gt;left + 1);     <span class="c">/* Width of source rectangular [byte] */</span>
    bwd = 3 * dev-&gt;wfbuf;                         <span class="c">/* Width of frame buffer [byte] */</span>
    for (y = rect-&gt;top; y &lt;= rect-&gt;bottom; y++) {
        memcpy(dst, src, bws);   <span class="c">/* Copy a line */</span>
        src += bws; dst += bwd;  <span class="c">/* Next line */</span>
    }

    return 1;    <span class="c">/* Continue to decompress */</span>
}


<span class="c">/*------------------------------*/</span>
<span class="c">/* Program Main                 */</span>
<span class="c">/*------------------------------*/</span>

int main (int argc, char* argv[])
{
    void *work;       <span class="c">/* Pointer to the decompressor work area */</span>
    JDEC jdec;        <span class="c">/* Decompression object */</span>
    JRESULT res;      <span class="c">/* Result code of TJpgDec API */</span>
    IODEV devid;      <span class="c">/* User defined device identifier */</span>

    <span class="c">/* Open a JPEG file */</span>
    if (argc &lt; 2) return -1;
    devid.fp = fopen(argv[1], "rb");
    if (!devid.fp) return -1;

    <span class="c">/* Allocate a work area for TJpgDec */</span>
    work = malloc(3100);

    <span class="c">/* Prepare to decompress */</span>
    res = jd_prepare(&amp;jdec, in_func, work, 3100, &amp;devid);
    if (res == JDR_OK) {
        <span class="c">/* Ready to dcompress. Image info is available here. */</span>
        printf("Image dimensions: %u by %u. %u bytes used.\n", jdec.width, jdec.height, 3100 - jdec.sz_pool);

        devid.fbuf = malloc(3 * jdec.width * jdec.height); <span class="c">/* Frame buffer for output image (assuming RGB888 cfg) */</span>
        devid.wfbuf = jdec.width;

        res = jd_decomp(&amp;jdec, out_func, 0);   <span class="c">/* Start to decompress with 1/1 scaling */</span>
        if (res == JDR_OK) {
            <span class="c">/* Decompression succeeded. You have the decompressed image in the frame buffer here. */</span>
            printf("\rOK  \n");

        } else {
            printf("Failed to decompress: rc=%d\n", res);
        }

        free(devid.fbuf);    <span class="c">/* Discard frame buffer */</span>

    } else {
        printf("Failed to prepare: rc=%d\n", res);
    }

    free(work);             <span class="c">/* Discard work area */</span>

    fclose(devid.fp);       <span class="c">/* Close the JPEG file */</span>

    return res;
}
</pre>

</div>

<div class="para" id="limits">
<h3>Limits</h3>
<ul>
<li>JPEG standard: Baseline only. Progressive and Lossless JPEG format are not supported.</li>
<li>Image size: Upto 65520 x 65520 pixels.</li>
<li>Colorspace: YCbCr three components only. Grayscale image is not supported.</li>
<li>Sampling factor: 4:4:4, 4:2:2 or 4:2:0.</li>
</ul>
</div>

<div class="para" id="memory">
<h3>Memory Usage</h3>
<p>These are the memory usage of some platforms at default configuration. All compilations are optimized in code size.</p>
<table class="lst2">
<tr><th></th><th>AVR</th><th>PIC24</th><th>CM0</th><th>IA-32</th></tr>
<tr><td>Compiler</td><td>GCC</td><td>C30</td><td>GCC</td><td>VC6</td></tr>
<tr class="lst3"><td>text+const</td><td>9422</td><td>6544</td><td>4536</td><td>6144</td></tr>
</table>
<p>As for the work area, TJpgDec requires upto 3100 bytes for most JPEG images. It exactly depends on what parameter has been used to create the JPEG image. The 3100 bytes is the maximum memory requirement at default input buffer configuration (<tt>JD_SZBUF == 512</tt>) and it varies with <tt>JD_SZBUF</tt>. The <tt>JD_SZBUF</tt> defines how many bytes read from input stream at a time. TJpgDec alignes each read request to the buffer size so that 512, 1024, 2048... byte is ideal to read from storage device.</p>
</div>


<div class="para" id="license">
<h3>About TJpgDec License</h3>
<p>This is a copy of the TJpgDec license document that included in the source codes.</p>
<pre>
/*----------------------------------------------------------------------------/
/ TJpgDec - Tiny JPEG Decompressor R0.01                       (C)ChaN, 2011
/-----------------------------------------------------------------------------/
/ The TJpgDec is a generic JPEG decompressor module for tiny embedded systems.
/ This is a free software that opened for education, research and commercial
/  developments under license policy of following terms.
/
/  Copyright (C) 2011, ChaN, all right reserved.
/
/ * The TJpgDec module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/
/----------------------------------------------------------------------------*/</pre>
<p>Therefore TJpgDec license is one of the BSD-style license but there is a big difference. Because TJpgDec is for embedded projects, the conditions for redistributions in binary form, such as embedded code, hex file and binary library, are not specified to increase its usability. The documentation of the distributions need not include about TJpgDec and its license document, and it may also. Of course TJpgDec is compatible with the projects under GNU GPL. When redistribute it with any modification, the license can also be changed to GNU GPL or BSD-style license.</p>
</div>

<p class="foot"><a href="../00index.html">Return</a></p>
</body>
</html>
